//============================================================================================
/**
 * @file	h_obst_generate.c
 * @brief	ポケスロン競技：障害物競走　障害物生成
 * @author	Nozomu Saito
 *
 * モジュール名：H_OBST_GENE_
 */
//============================================================================================

#include "common.h"
#include "system/arc_util.h"
#include "pkthln_hurdle_cmn_def.h"
#include "../pkthln_act_def.h"
#include "h_obst_generate.h"

#define OBST_POS_NUM	(512)		//1レーンにおける障害物の位置数(レーン距離を4096ドットして、8ドット単位で置けるとしたときの値)
#define HURDLE_CRS_NUM	(3)

typedef struct H_OBST_LIST_tag
{
	H_OBST_PTR ObstArray;
	int AddPoint;
}H_OBST_LIST;

typedef struct H_OBST_DATA_tag
{
	u8 OrgData[LANE_NUM][OBST_POS_NUM];
	u8 Data[LANE_NUM][OBST_POS_NUM];
}H_OBST_DATA;

typedef struct H_OBST_GENERATE_tag
{
	H_OBST_LIST ObstList[LANE_NUM];
	H_OBST_DATA ObstData;
	int GeneratePos[LANE_NUM];
}H_OBST_GENERATE;

//--------------------------------------------------------------------------------------------
/**
 * @brief	ジェネレート
 *
 * @param	ptr				ジェネレータポインタ
 * @param	inLane			生成レーン
 * @param	inAddPos		生成場所（Y座標）
 * @return	H_OBST_PTR		生成した（アクティブにした）オブジェクトポインタ
 */
//--------------------------------------------------------------------------------------------
static H_OBST_PTR Generate(H_OBST_GENERATE_PTR ptr, const u8 inLane, const int inAddPos)
{
	H_OBST_PTR obst_ptr;
	u8 add_point = ptr->ObstList[inLane].AddPoint;

	obst_ptr = H_OBST_GetObstPtr(ptr->ObstList[inLane].ObstArray, add_point);

	//追加ポイントのOBJは生きているかチェック（生きているなら、追加量過多で追加しない。というよりその場合はバグのはず）
	if ( H_OBST_IsValid(obst_ptr) ){
		GF_ASSERT(0);
		return NULL;
	}

	//追加ポイントのシフト
	ptr->ObstList[inLane].AddPoint = (ptr->ObstList[inLane].AddPoint+1) % OBST_NUM;

	//座標セット
	{
		VecFx32 vec = { 0,-8*FX32_ONE,0 };
		vec.y += inAddPos*FX32_ONE;
		switch(inLane){
		case 0:
			vec.x = FX32_CONST(48);
			break;
		case 1:
			vec.x = FX32_CONST(128);
			break;
		case 2:
			vec.x = FX32_CONST(208);
			break;
		}
		H_OBST_SetPos(obst_ptr, &vec);
	}

	//アクティブにする
	H_OBST_SetActive(obst_ptr, 1);

	//タイプセット
///	ptr->ObstList[inLane].Obst[add_point].Type = inType;
	//OBJポインタセット(ビジブル)
	//ptr->ObstList[inLane].Obst[add_point].ObjPtr;

	return obst_ptr;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ジェネレータ初期化
 * @param	inHeapID	ヒープID
 *
 * @return	ジェネレータポインタ
 */
//--------------------------------------------------------------------------------------------
H_OBST_GENERATE_PTR H_OBST_GENE_Init(const int inHeapID)
{
	int i;
	H_OBST_GENERATE_PTR ptr;
	int size = sizeof(H_OBST_GENERATE);
	ptr = sys_AllocMemory(inHeapID, size);
	MI_CpuClear8(ptr, size);
	//障害物OBJアロケーション
	for(i=0;i<LANE_NUM;i++){
		ptr->ObstList[i].ObstArray = H_OBST_Alloc(OBST_NUM, inHeapID);
	}
	return ptr;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ジェネレータ解放
 * @param	ptr				ジェネレータポインタ
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void H_OBST_GENE_Free(H_OBST_GENERATE_PTR ptr)
{
	int i;
	for(i=0;i<LANE_NUM;i++){
		H_OBST_Free( ptr->ObstList[i].ObstArray );
	}
	sys_FreeMemoryEz(ptr);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ジェネレータセットアップ
 * @param	ptr				ジェネレータポインタ
 * @param	act_cnt_ptr		オブジェクトコントロールポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void H_OBST_GENE_SetUp(H_OBST_GENERATE_PTR ptr, PKTHLN_CLACT_CNT_PTR act_cnt_ptr)
{
	//各レーンで管理するオブジェクトをポインタとしてオブジェクトコントローラからもらう
	int i,j;
	H_OBST_PTR obst_ptr;

	for(i=0;i<LANE_NUM;i++){
		for(j=0;j<OBST_NUM;j++){
			obst_ptr = H_OBST_GetObstPtr(ptr->ObstList[i].ObstArray, j);
			H_OBST_SetObjPtr(obst_ptr,
					PkthlnClAct_GetActPtr(act_cnt_ptr, RES_CODE_OBST, ACT_CODE_OBST),
					PkthlnClAct_GetActPtr(act_cnt_ptr, RES_CODE_OBST_BREAK, ACT_CODE_OBST_BREAK) );
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物リストポインタを返す
 * @param	ptr			ジェネレータポインタ
 * @param	inLane		取得したいレーン
 *
 * @return	list_ptr		リストポインタ
 */
//--------------------------------------------------------------------------------------------
H_OBST_PTR H_OBST_GENE_GetObstArray(H_OBST_GENERATE_PTR ptr, const u8 inLane)
{
	GF_ASSERT(inLane < LANE_NUM);
	return ptr->ObstList[inLane].ObstArray;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物配置データポインタを返す(送るデータ)
 * @param	ptr			ジェネレータポインタ
 *
 * @return	void *		データ先頭ポインタ
 */
//--------------------------------------------------------------------------------------------
void *H_OBST_GENE_GetObstSendDataPtr(H_OBST_GENERATE_PTR ptr)
{
	return ptr->ObstData.OrgData[0];
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物配置データポインタを返す（格納側データ）
 * @param	ptr			ジェネレータポインタ
 *
 * @return	void *		データ先頭ポインタ
 */
//--------------------------------------------------------------------------------------------
void *H_OBST_GENE_GetObstDataPtr(H_OBST_GENERATE_PTR ptr)
{
	return ptr->ObstData.Data[0];
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物配置データサイズを返す
 * @param	ptr			ジェネレータポインタ
 *
 * @return	int			データサイズ
 */
//--------------------------------------------------------------------------------------------
int H_OBST_GENE_GetObstDataSize(H_OBST_GENERATE_PTR ptr)
{
	return (LANE_NUM*OBST_POS_NUM);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ジェネレート
 * @param	ptr			ジェネレータポインタ
 * @param	inLength	走行距離
 * @param	inLane		レーン
 *
 * @return	BOOL 		TRUE:生成	FALSE:非生成
 */
//--------------------------------------------------------------------------------------------
void H_OBST_GENE_Generate(H_OBST_GENERATE_PTR ptr, const int inLength, const u8 inLane)
{
	int pos;
	int data;
	int add_pos;
	//データの場所を計算
	pos = inLength / 8;

	if (pos == 0){
		return;
	}

	//追加位置の補正
	add_pos = inLength - (pos*8);

	//インデックス化
	pos-=1;

	//データ打ち止め
	if (pos>=OBST_POS_NUM){
		return;
	}

	//指定位置のデータを参照する
	data = ptr->ObstData.Data[inLane][pos];
	//障害物データがあるか？
	if (data){
		//計算した位置のデータは生成済みか？
		if(ptr->GeneratePos[inLane] < pos){
			//生成を記憶
			ptr->GeneratePos[inLane] = pos;
			//生成
			Generate(ptr, inLane, add_pos);
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	生成データの作成
 * @param	ptr			ジェネレータポインタ
 *
 * @return	BOOL 		TRUE:生成	FALSE:非生成
 */
//--------------------------------------------------------------------------------------------
void H_OBST_GENE_MakeGenerateData(H_OBST_GENERATE_PTR ptr)
{
	u8 *data;
	u8 no;
	data = ptr->ObstData.OrgData[0];
	//コースは３つからランダム
	no = gf_rand() % HURDLE_CRS_NUM;
	//アーカイブからロード
	ArchiveDataLoad(data, ARC_PKTHEV_DASH_DAT, no);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物データの有無を調べる
 * @param	ptr			ジェネレータポインタ
 * @param	inLane		レーンナンバー
 * @param	inLen		走行距離
 *
 * @return	pos 		0以上:ある	-1:ない
 */
//--------------------------------------------------------------------------------------------
int H_OBST_GENE_IsObstData(H_OBST_GENERATE_PTR ptr, const int inLane, const int inLen)
{
	int pos;
	//データの場所を計算
	pos = inLen / 8;

	if ( ptr->ObstData.Data[inLane][pos]){
		return pos;
	}

	return -1;
}


